/**
 * UserDataManager - 用户数据管理模块
 * 
 * 职责:
 * 1. 管理用户数据的本地存储和获取
 * 2. 处理会话状态跨标签页同步
 * 3. 提供Cookie清理功能
 * 4. 实现用户状态监控
 */


// 添加到user_data.js或作为工具函数
function mergeDeep(target, source) {
    const output = Object.assign({}, target);
    
    if (isObject(target) && isObject(source)) {
        Object.keys(source).forEach(key => {
            if (isObject(source[key])) {
                if (!(key in target)) {
                    Object.assign(output, { [key]: source[key] });
                } else {
                    output[key] = mergeDeep(target[key], source[key]);
                }
            } else {
                Object.assign(output, { [key]: source[key] });
            }
        });
    }
    
    return output;
}

function isObject(item) {
    return (item && typeof item === 'object' && !Array.isArray(item));
}

// 用户数据相关的包装方法
const UserDataCache = {
    /**
     * 保存用户数据到本地存储
     * @param {string} [key='userData'] - 数据存储的键名
     * @param {Object} userData - 用户数据
     * @param {number} [expiryMs] - 过期时间(毫秒)，默认7天
     * @returns {Promise<Object>} - 保存的用户数据
     */
    async saveUserData(userData, key='userData', expiryMs = 7 * 24 * 60 * 60 * 1000) {
        LocalCache.removeItem(key);
        if (!userData) return null;
        
        try {
            // 移除敏感数据
            const safeData = {...userData};
            if (safeData.data && safeData.data.password) {
                delete safeData.data.password;
            }
            
            // 添加额外信息
            safeData._lastUpdated = Date.now();
            
            await LocalCache.setItem(key, safeData, expiryMs);
            console.log('用户数据已保存到本地缓存');
            
            // 触发自定义事件
            document.dispatchEvent(new CustomEvent('userDataUpdated', { 
                detail: safeData 
            }));
            
            return safeData;
        } catch (err) {
            console.error('保存用户数据失败:', err);
            return null;
        }
    },
    
    /**
     * 获取用户数据
     * @param {string} [key='userData'] - 数据存储的键名
     * @returns {Promise<Object|null>} - 用户数据或null
     */
    async getUserData(key='userData') {
        return await LocalCache.getItem(key, null);
    },
    
    /**
     * 更新用户数据的部分字段
     * @param {string} [key='userData'] - 数据存储的键名
     * @param {Object} updates - 要更新的字段, 例如：{ data: { name: 'Alice' } }
     * @param {string} [key='userData'] - 数据存储的键名
     * @returns {Promise<Object|null>} - 更新后的用户数据或null
     */
    async updateUserData(key='userData', updates) {
        if (!updates) return null;
        
        try {
            const userData = await this.getUserData();
            if (!userData) return null;
            
            // 深度合并用户数据
            const updatedData = mergeDeep(userData, updates);
            updatedData._lastUpdated = Date.now();
            
            // 获取原TTL
            const ttl = await LocalCache.getTimeToLive(key);
            const expiryMs = ttl || (7 * 24 * 60 * 60 * 1000); // 如果无法获取，使用默认值
            
            // 保存更新后的数据
            await LocalCache.setItem(key, updatedData, expiryMs);
            
            // 触发自定义事件
            document.dispatchEvent(new CustomEvent('userDataUpdated', { 
                detail: updatedData 
            }));
            
            return updatedData;
        } catch (err) {
            console.error('更新用户数据失败:', err);
            return null;
        }
    },
    
    /**
     * 清除用户数据
     * @param {string} [key='userData'] - 数据存储的键名
     * @returns {Promise<void>}
     */
    async clearUserData(key='userData') {
        try {
            await LocalCache.removeItem(key);
            console.log('用户数据已清除');
            
            // 触发自定义事件
            document.dispatchEvent(new CustomEvent('userDataCleared'));
        } catch (err) {
            console.error('清除用户数据失败:', err);
        }
    },
    /**
     * 用户是否已经登录
     * @returns {Promise<boolean>} - 是否已登录，true表示已登录
    */
    async isUserLoggedIn() {
        const userData = await this.getUserData();
        const hasUser = !!(userData && userData.data && userData.data.user_id);
        const isExpired = await this.isUserDataExpired();
        
        // 用户已经登录且未过期
        if (hasUser && !isExpired) {
            return true;
        } else if (hasUser && isExpired) {
            // 如果数据已过期，可能需要清除
            await this.clearUserData();
            return false;
        } else {
            return false;
        }
    },
    
    /**
     * 检查用户数据是否过期
     * @param {number} [maxAge=3600000] - 最大有效期(毫秒)，默认1小时
     * @returns {Promise<boolean>} - 是否需要刷新，true表示需要刷新
     */
    async isUserDataExpired(key='userData', maxAge = 3600000) {
        try {
            const ttl = await LocalCache.getTimeToLive(key);
            // 如果没有TTL或者TTL小于指定的最大有效期，则认为过期
            return !ttl || ttl < maxAge;
        } catch (err) {
            console.error('检查用户数据过期状态失败:', err);
            return true;
        }
    }
};

/**
 * 会话安全性检查 - 定期检查服务器端会话状态
 */
class SessionChecker {
    constructor(options = {}) {
        this.checkInterval = options.interval || 300000; // 默认每30秒检查一次
        this.endpoint = options.endpoint || '/user/check-session';
        this.checkerId = null;
        this.onSessionInvalid = options.onSessionInvalid || this.defaultSessionInvalidHandler;
        this.lastCheckTime = null;
        this.isChecking = false;
    }

    // 启动会话检查
    start() {
        if (this.checkerId) {
            console.log('会话检查器已在运行中');
            return;
        }
        
        // 立即执行一次检查
        this.checkSession();
        
        // 设置定时检查
        this.checkerId = setInterval(() => {
            this.checkSession();
        }, this.checkInterval);
        
        console.log('会话检查器已启动');
    }
    
    // 停止会话检查
    stop() {
        if (this.checkerId) {
            clearInterval(this.checkerId);
            this.checkerId = null;
            console.log('会话检查器已停止');
        }
    }
    
    // 执行会话检查
    async checkSession() {
        if (this.isChecking) return; // 防止重复检查
        
        this.isChecking = true;
        try {
            const response = await fetch(this.endpoint, {
                method: 'GET',
                credentials: 'same-origin',
                headers: { 'X-Requested-With': 'XMLHttpRequest' }
            });
            
            if (!response.ok) {
                if (response.status === 401 || response.status === 403) {
                    console.log('会话检查失败: 未授权');
                    this.onSessionInvalid('unauthorized');
                    this.stop();
                    return;
                }
                console.warn(`会话检查请求失败: ${response.status}`);
                return;
            }
            
            const data = await response.json();
            this.lastCheckTime = new Date();
            
            if (!data.authenticated) {
                console.log('服务器返回未认证状态');
                this.onSessionInvalid('unauthenticated');
                this.stop();
            }
        } catch (err) {
            console.warn('会话状态检查错误:', err);
            // 网络错误不触发登出
        } finally {
            this.isChecking = false;
        }
    }
    
    // 默认的会话无效处理函数
    defaultSessionInvalidHandler(reason) {
        console.log(`会话已失效(${reason})，需要重新登录`);
        // 这里实际上不做任何操作，由具体实现决定
    }
}

/**
 * 多标签页通信管理器 - 处理标签页间的同步
 */
class TabSyncManager {
    constructor(options = {}) {
        this.channelName = options.channelName || 'yourong_user_channel';
        this.channel = null;
        this.handlers = {};
        this.supported = 'BroadcastChannel' in window;
    }
    
    // 初始化通信通道
    init() {
        if (!this.supported) {
            console.warn('当前浏览器不支持BroadcastChannel，标签页同步功能将不可用');
            return false;
        }
        
        try {
            this.channel = new BroadcastChannel(this.channelName);
            this.channel.onmessage = this.handleMessage.bind(this);
            console.log('标签页同步通道已初始化');
            return true;
        } catch (e) {
            console.error('标签页同步通道初始化失败:', e);
            this.supported = false;
            return false;
        }
    }
    
    // 处理接收到的消息
    handleMessage(event) {
        const { type, data } = event.data;
        
        if (this.handlers[type]) {
            this.handlers[type](data);
        }
    }
    
    // 注册消息处理函数
    on(type, handler) {
        if (typeof handler === 'function') {
            this.handlers[type] = handler;
        }
    }
    
    // 发送消息到所有标签页
    broadcast(type, data = {}) {
        if (!this.supported || !this.channel) return false;
        
        try {
            this.channel.postMessage({ type, data });
            return true;
        } catch (e) {
            console.error(`发送消息失败(${type}):`, e);
            return false;
        }
    }
    
    // 关闭通道
    destroy() {
        if (this.channel) {
            this.channel.close();
            this.channel = null;
        }
    }
}

/**
 * Cookie管理器 - 处理身份验证相关的Cookie操作
 */
class CookieManager {
    // 清除所有Cookies
    static clearAllCookies() {
        const cookies = document.cookie.split(";");
        
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i];
            const eqPos = cookie.indexOf("=");
            const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
            
            if (!name) continue;
            
            // 删除当前路径的cookie
            document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
            
            // 删除根路径的cookie
            document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;`;
            
            // 尝试不同的域配置
            const domain = window.location.hostname;
            document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domain}`;
            
            // 如果是子域名，尝试清除主域名的cookie
            if (domain.indexOf('.') !== -1) {
                const mainDomain = domain.substring(domain.indexOf('.'));
                document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${mainDomain}`;
            }
        }
        
        console.log('已清除所有cookies');
        return true;
    }
    
    // 清除特定的身份验证相关cookies
    static clearAuthCookies() {
        const authCookies = [
            'session',                     // Flask会话cookie
            'remember_token',              // Flask-Login记住我cookie
            'yourong_bbs_remember_token',  // 自定义记住我cookie
            'yourong_bbs_session'          // 自定义会话cookie
        ];
        
        authCookies.forEach(cookieName => {
            document.cookie = `${cookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
            document.cookie = `${cookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;`;
            
            const domain = window.location.hostname;
            document.cookie = `${cookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=${domain}`;
        });
        
        console.log('已清除身份验证相关cookies');
        return true;
    }
}

/**
 * 用户会话管理器 - 处理用户登录状态和会话
 * 核心类，整合其他功能模块
 */
class UserSessionManager {
    constructor() {
        // 初始化标签页同步管理器
        this.tabSync = new TabSyncManager({ 
            channelName: 'yourong_user_session'
        });
        
        // 初始化会话检查器
        this.sessionChecker = new SessionChecker({
            onSessionInvalid: this.handleInvalidSession.bind(this)
        });
        
        this._initialized = false;
        this._currentUserId = null;
    }
    
    // 初始化用户会话管理器
    async init() {
        if (this._initialized) return true;
        
        // 初始化标签页同步
        this.tabSync.init();
        
        // 注册消息处理函数
        this.tabSync.on('logout', this.handleRemoteLogout.bind(this));
        this.tabSync.on('login', this.handleRemoteLogin.bind(this));
        
        // 获取当前用户数据
        try {
            const userData = await UserDataCache.getUserData();
            if (userData && userData.data && userData.data.user_id) {
                this._currentUserId = userData.data.user_id;
                this.sessionChecker.start(); // 开始会话检查
                this._initialized = true;
                return true;
            }
        } catch (err) {
            console.error('初始化用户会话管理器失败:', err);
        }
        
        this._initialized = true;
        return false;
    }
    
    // 处理服务器端会话失效
    handleInvalidSession(reason) {
        console.log(`会话已失效(${reason})，执行本地登出`);
        this.logout(false);  // 执行本地登出，不通知服务器
    }
    
    // 处理远程标签页的登出消息
    handleRemoteLogout(data) {
        console.log('收到其他标签页的登出通知，执行本地登出');
        // 不广播消息，防止循环
        this.performLocalLogout(false);
        
        // 显示通知
        if (typeof window.show_noti === 'function') {
            window.show_noti('您已在其他标签页登出', 'info');
        }
    }
    
    // 处理远程标签页的登录消息
    handleRemoteLogin(data) {
        console.log('收到其他标签页的登录通知');
        
        // 如果有用户数据，刷新本地缓存
        if (data && data.userData) {
            UserDataCache.saveUserData(data.userData);
        }
        
        // 刷新页面以更新状态
        window.location.reload();
    }
    
    // 执行本地登出操作
    async performLocalLogout(broadcast = true) {
        // 清除本地存储
        await UserDataCache.clearUserData();
        
        // 停止会话检查
        this.sessionChecker.stop();
        
        // 清除cookies
        CookieManager.clearAuthCookies();
        
        // 广播登出消息到其他标签页
        if (broadcast && this.tabSync && this._initialized) {
            this.tabSync.broadcast('logout', {
                timestamp: new Date().toISOString(),
                userId: this._currentUserId
            });
        }
        
        this._currentUserId = null;
    }
    
    // 登出用户 - 包括服务器请求和本地清理
    async logout(notifyServer = true) {
        // 先执行本地登出
        await this.performLocalLogout(true);
        
        // 如果需要通知服务器
        if (notifyServer) {
            try {
                const response = await fetch('/user/logout', {
                    method: 'GET',
                    credentials: 'same-origin'
                });
                
                console.log('服务器登出响应状态:', response.status);
            } catch (err) {
                console.error('服务器登出请求失败:', err);
            }
        }
        
        // 重定向到登录页面或刷新当前页
        if (notifyServer) {
            window.location.href = '/user/login';
        } else {
            window.location.reload();
        }
    }
    
    // 切换用户
    async switchUser() {
        await this.logout(true);
    }
    
    // 资源清理
    destroy() {
        this.sessionChecker.stop();
        this.tabSync.destroy();
    }
}

window.UserDataCache = UserDataCache;

// 实例化用户会话管理器
const userSessionManager = new UserSessionManager();

// 导出为全局函数
window.mergeDeep = mergeDeep;
// 导出Cookie管理器函数
window.clearAllCookies = CookieManager.clearAllCookies;
window.clearAuthCookies = CookieManager.clearAuthCookies;

// 导出登出简便方法
window.logout = function() {
    return userSessionManager.logout();
};
// 导出切换用户方法
window.switchUser = function() {
    return userSessionManager.switchUser();
};

// DOMContentLoaded时初始化用户会话管理器
document.addEventListener('DOMContentLoaded', function() {
    userSessionManager.init().then(initialized => {
        console.log('用户会话管理器初始化状态:', initialized ? '成功' : '未登录');
    });
});



